<template lang="pug">
.roomWrap
  .boardWrap(:style="`padding: ${getClientWidth(0.05)}px 0`")
    canvas(
      ref="canvas",
      :style="`width: ${canvasSize / SCALE}px;height: ${canvasSize / SCALE}px`",
      :width="canvasSize",
      :height="canvasSize"
    )
  .btmWrap(:style="`top: ${getClientWidth()}px`")
    .operateWrap.operateColorWrap
      .item(
        @click="lineColor = color",
        v-for="color in colorList",
        :key="color",
        :style="`background-color: ${color};${color == lineColor ? 'border-width: 4px;' : ''}`"
      )
    .operateWrap.operateLineWrap
      .item(
        @click="lineWidth = line",
        v-for="line in lineList",
        :key="line",
        :style="`${line == lineWidth ? 'border-width: 4px;' : ''}${lineColor == 'white' ? 'background-color: #000;' : ''};`"
      )
        .line(
          :style="`height: ${line}px;width: ${line}px;background-color: ${lineColor};`"
        )
    .clearBtn(@click="clearAll") 清空画布
    .clearBtn(@click="returnLast") 撤回一步
    .clearBtn(@click="saveImg") 保存图片
</template>

<script lang="ts">
import { Vue } from "vue-class-component";

interface historyList {
  x: number;
  y: number;
  lineWidth: number;
  lineColor: string;
  isClearAll: boolean;
}

let canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D;
export default class Home extends Vue {
  /**
   * @default 4
   * @description 画笔尺寸
   */
  public lineWidth: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 = 4;
  /**
   * @default #000
   * @description 画笔颜色
   */
  public lineColor:
    | "red"
    | "orange"
    | "yellow"
    | "green"
    | "cyan"
    | "blue"
    | "purple"
    | "black"
    | "white" = "black";

  colorList = [
    "red",
    "orange",
    "yellow",
    "green",
    "cyan",
    "blue",
    "purple",
    "black",
    "white",
  ];
  lastHistory: Array<Partial<historyList>> = [];
  historyList: Array<Array<Partial<historyList>>> = [];
  lineList = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
  readonly SCALE = window.devicePixelRatio || 4;
  readonly canvasSize = this.getClientWidth(0.9) * this.SCALE;

  getClientWidth(scale: number | undefined = 1): number {
    return ~~(document.body.clientWidth * scale);
  }
  clearAll() {
    if (!this.historyList.length) return;

    this.historyList.push([
      {
        isClearAll: true,
      },
    ]);
    ctx.clearRect(
      0,
      0,
      this.canvasSize / this.SCALE,
      this.canvasSize / this.SCALE
    );
  }
  returnLast() {
    ctx.clearRect(
      0,
      0,
      this.canvasSize / this.SCALE,
      this.canvasSize / this.SCALE
    );

    if (this.historyList.length) {
      this.historyList.pop();

      let i =
        this.historyList.map((i) => i[0].isClearAll).lastIndexOf(true) + 1;

      for (; this.historyList[i]; i++) {
        const lineList = this.historyList[i];

        ctx.beginPath();
        ctx.lineCap = "round";

        for (var j = -1; lineList[++j]; ) {
          const obj = lineList[j];

          ctx.strokeStyle = obj.lineColor as string;
          ctx.lineWidth = obj.lineWidth as number;
          const x = obj.x as number;
          const y = obj.y as number;
          ctx.lineTo(x, y);
          ctx.stroke();
        }
        ctx.stroke();
      }
    }
  }
  saveImg() {
    const base64 = canvas.toDataURL();
    const a = document.createElement("a");
    a.href = base64;
    a.download = "";
    a.click();
  }

  mounted() {
    canvas = this.$refs.canvas as HTMLCanvasElement;
    ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
    ctx.scale(this.SCALE, this.SCALE);
    const gbcr = canvas.getBoundingClientRect();

    document.addEventListener("touchstart", (event) => {
      if (event.target !== canvas) return;
      ctx.beginPath();
      ctx.lineWidth = this.lineWidth;
      ctx.lineCap = "round";
      ctx.strokeStyle = this.lineColor;
    });
    document.addEventListener("touchmove", (event) => {
      if (event.target !== canvas) return;
      const x = event.touches[0].clientX - gbcr.left;
      const y = event.touches[0].clientY - gbcr.top;
      this.lastHistory.push({
        x,
        y,
        lineColor: this.lineColor,
        lineWidth: this.lineWidth,
      });
      ctx.lineTo(x, y);
      ctx.stroke();
    });
    document.addEventListener("touchend", (event) => {
      if (event.target !== canvas) return;
      this.historyList.push(this.lastHistory);
      this.lastHistory = [];
    });
  }
}
</script>

<style lang="scss" scoped>
$outlineColor: #efefef;

.roomWrap {
  height: 100vh;
  overflow: hidden;
  .boardWrap {
    display: flex;
    justify-content: center;
    background-color: #efefef;
    position: fixed;
    width: 100%;

    canvas {
      background-color: #fff;
    }
  }
  .btmWrap {
    position: fixed;
    width: 100%;
    height: calc(100vh - 100vw);
    overflow-y: auto;
    overflow: hidden;
    .operateWrap {
      height: 40px;
      display: flex;
      align-items: center;
      padding-right: 10px;
      width: calc(100vw - 10px);
      overflow-x: auto;
      .item {
        margin-left: 10px;
        flex-shrink: 0;
        width: 20px;
        height: 20px;
        border-radius: 20px;
        border: 1px solid $outlineColor;
      }
    }
    .operateLineWrap {
      .item {
        display: flex;
        overflow: hidden;
        align-items: center;
        justify-content: center;
        .line {
          border-radius: 50px;
        }
      }
    }
    .clearBtn {
      margin: 10px 10px 0;
      padding: 5px 10px;
      text-align: center;
      background-color: orange;
      border-radius: 4px;
      color: #fff;
      margin-left: 10px;
    }
  }
}
</style>